package com.test.socket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class EchoSelectorProtocol implements TCPProtocol {

	private int bufSize;//size of i/o buffer
	public EchoSelectorProtocol(int bufSize){
		this.bufSize =bufSize;
	}
	@Override
	public void handleAccept(SelectionKey key) throws IOException {
		SocketChannel clntChannel = ((ServerSocketChannel)key.channel()).accept();
		clntChannel.configureBlocking(false);//must be nonblocking to register
		//register the selector with new channel for read and attach byte buffer
		clntChannel.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocate(bufSize));
		
	}

	@Override
	public void handleRead(SelectionKey key) throws IOException {
		//client socket channel has pending data
		SocketChannel clntChannel = (SocketChannel)key.channel();
		ByteBuffer buffer = (ByteBuffer)key.attachment();
		long bytesRead = clntChannel.read(buffer);
		if (bytesRead==-1) {
			//did the other end close?
			clntChannel.close();
		}else if (bytesRead>0) {
			//indicate via key that reading/writing are both of interest now
			key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
		}
		
	}

	@Override
	public void handleWrite(SelectionKey key) throws IOException {
		/**
		 * channel is available for writing ,and key is valid(i.e.,client channel not closed)
		 */
		//retrieve data read earlier
		ByteBuffer buf = (ByteBuffer)key.attachment();
		buf.flip();//prepare buffer for writing
		SocketChannel clChannel = (SocketChannel)key.channel();
		clChannel.write(buf);
		if (!buf.hasRemaining()) {//buffer completely written?
			//nothing left ,so no longer interested in writes
			key.interestOps(SelectionKey.OP_READ);
		}
		buf.compact();//make room for more data to be read in
	}

}
